package keer.httpinterface.http;

import keer.httpinterface.HttpInterfaceException;
import keer.httpinterface.utils.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 用户保存所有http请求/响应头的集合类
 *
 * @author Keer
 * @since 1.0.0
 */
public class Headers {
    private final static String CONTENT_TYPE = "Content-Type";
    private final static String CONTENT_LENGTH = "Content-Length";
    private final static String CONTENT_ENCODING = "Content-Encoding";
    private final static String COOKIE = "Cookie";
    private final static String TRANSFER_ENCODING = "Transfer-Encoding";

    public final static Headers EMPTY_HEADERS = new Headers();
    private final Map<String, List<String>> headers;

    /**
     * 公共无参构造方法，用于创建一个不包含任何请求/响应头的实例
     */
    public Headers() {
        this.headers = new HashMap<>();
    }

    /**
     * 构造方法，使用一个已有的请求头实例来创建一个新实例
     * @param headers 现有请求/响应头实例
     */
    public Headers(Headers headers) {
        this.headers = new HashMap<>();
        if (headers != null) {
            this.headers.putAll(headers.headers);
        }
    }

    /**
     * 构造方法，使用一个已有的请求/响应头map来创建一个新实例
     * @param map 请求头map
     */
    public Headers(Map<String,List<String>> map) {
        this.headers = new HashMap<>();
        for (String key : map.keySet()) {
            headers.put(parseKey(key), map.get(key));
        }
    }

    /**
     * 返回所有请求/响应头
     * @return
     */
    public Map<String, List<String>> all() {
        return Collections.unmodifiableMap(headers);
    }

    /**
     * 返回指定key的请求/响应头，如果请求/响应头不存在，返回null
     * @param key 请求/响应头key
     * @return 请求头集合
     */
    public List<String> get(String key) {
        return headers.get(parseKey(key));
    }

    /**
     * 返回指定key的第一个请求头，如果请求头不存在，返回null
     * @param key 请求/响应头key
     * @return 请求/响应头
     */
    public String getOne(String key) {
        List<String> list = get(parseKey(key));
        if (list == null) {
            return null;
        }
        return list.get(list.size() - 1);
    }

    /**
     * 返回指定key的第一个请求/响应头，如果请求/响应头不存在，返回defaultValue
     * @param key 请求/响应头key
     * @param defaultValue 默认值
     * @return 请求/响应头
     */
    public String getOneOrDefault(String key, String defaultValue) {
        String one = getOne(key);
        if (one == null) {
            one = defaultValue;
        }
        return one;
    }

    /**
     * 添加一个请求/响应头
     * @param key 请求/响应头key
     * @param value 请求/响应头value
     */
    public void put(String key, String...value) {
        if (this == EMPTY_HEADERS) {
           throw new UnsupportedOperationException("Can't modify empty headers");
        }
        headers.put(parseKey(key), Arrays.asList(value));
    }

    /**
     * 添加一个请求/响应头，格式为key:value
     * @param header 请求/响应头，格式为key:value
     */
    public void put(String header) {
        if (StringUtils.isBlank(header)) {
            return;
        }
        int idx = header.indexOf(":");
        String k = "";
        String v = header;
        if (idx >= 0) {
            k = header.substring(0, idx).trim();
            v = header.substring(idx + 1).trim();
        }
        put(k, v);
    }

    /**
     * 添加多个请求/响应头
     * @param headers 多个请求/响应头
     */
    public void putAll(Headers headers) {
        if (headers != null && headers.headers != null) {
            this.headers.putAll(headers.headers);
        }
    }

    /**
     * 获取Content-Type
     * @return HttpContentType
     */
    public HttpContentType contentType() {
        String contentType = getOne(CONTENT_TYPE);
        HttpContentType ct = null;
        try {
            ct = HttpContentType.of(contentType);
        } catch (HttpInterfaceException e) {
            throw new RuntimeException(e);
        }
        return ct;
    }

    /**
     * 设置Content-Type
     * @param contentType HttpContentType
     */
    public void setContentType(HttpContentType contentType) {
        put(CONTENT_TYPE, contentType.toString());
    }

    /**
     * 获取Content-Type的编码，默认为UTF-8
     * @return 编码
     */
    public String charset() {
        HttpContentType contentType = contentType();
        return contentType == null ? StandardCharsets.UTF_8.name() : contentType.getCharset();
    }

    /**
     * 获取Cookie
     * @return Cookie
     */
    public String cookie() {
        return getOne(COOKIE);
    }

    /**
     * 获取Content-Length，默认值为-1
     * @return 请求体长度,默认值为-1，表示头信息中不包含Content-Length
     */
    public long contentLength() {
        return Long.parseLong(getOneOrDefault(CONTENT_LENGTH, "-1"));
    }

    /**
     * 获取Content-Encoding
     * @return 编码
     */
    public String contentEncoding() {
        return getOneOrDefault(CONTENT_ENCODING, null);
    }

    /**
     * 获取Transfer-Encoding
     * @return 编码
     */
    public String transferEncoding() {
        return getOneOrDefault(TRANSFER_ENCODING, null);
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        if (headers != null && !headers.isEmpty()) {
            for (String key : headers.keySet()) {
                List<String> values = headers.get(key);
                if (values != null) {
                    for (String v : values) {
                        builder.append(StringUtils.isBlank(key) ? "" : key + ":").append(v).append("\n");
                    }
                }
            }
            builder.setLength(builder.length() - 1);
        }
        return builder.toString();
    }

    private String parseKey(String key) {
        if (StringUtils.isBlank(key)) {
            return key;
        }
        key = key.trim().toLowerCase();
        String[] arr = key.split("-");
        StringBuilder builder = new StringBuilder();
        for (String s : arr) {
            builder.append(s.substring(0, 1).toUpperCase())
                    .append(s.substring(1))
                    .append("-");
        }
        builder.deleteCharAt(builder.length() - 1);
        return builder.toString();
    }
}
